package org.geekbang.thinking.in.spring.configuration.metadata;

import com.think.in.spring.ioc.overview.domain.User;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.util.ObjectUtils;

/**
 *
 * 配置元信息 demo
 * @author zjiajia
 * @date 2022/3/1 20:40
 */

public class BeanConfigurationMetadataDemo {

    public static void main(String[] args) {

        // beanDefinitionBuilder
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
        // 添加属性 ，实际起作用的属性
        beanDefinitionBuilder.addPropertyValue("name","test");
        // 获取BeanDefinition
        AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
        // 附加属性，如果不做任何处理，并不会影像到 最后属性的值
        // 不影响 Bean populate /initialize 这个过程
        beanDefinition.setAttribute("name","小马哥");
        // BeanDefinition 的来源
        beanDefinition.setSource(BeanConfigurationMetadataDemo.class);
        // beanFactory
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // 通过后置处理器，来处理附加属性，然后达到扩展的目的
        beanFactory.addBeanPostProcessor(new BeanPostProcessor() {
            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                if(ObjectUtils.nullSafeEquals("user",beanName) && User.class.equals(bean.getClass())){
                    //从工厂获取到 user 的 BeanDefinition
                    BeanDefinition bd = beanFactory.getBeanDefinition("user");
                    // 对附加属性进行处理
                    if(BeanConfigurationMetadataDemo.class.equals(bd.getSource())){
                        String name = (String) bd.getAttribute("name");
                        User user = (User)bean;
                        user.setName(name);
                    }


                }
                return bean;
            }
        });
        beanFactory.registerBeanDefinition("user",beanDefinition);
        User user = beanFactory.getBean("user", User.class);
        System.out.println(user);

    }
}
